package com.domainlanguage.base;

import org.hibernate.type.ImmutableType;
import org.hibernate.type.Type;
import org.hibernate.HibernateException;
import org.hibernate.Hibernate;
import static org.hibernate.Hibernate.*;
import org.hibernate.engine.SessionImplementor;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.util.Arrays;
import java.util.Properties;
import java.math.BigDecimal;

import com.domainlanguage.time.ImmutableCompositeUserType;

/**
 * Hibernate type for Ratio.
 * 
 */
public class RatioType extends ImmutableCompositeUserType {

    @Override
    public String[] getPropertyNames() {
        return new String[] {"numerator", "denominator"};
    }

    @Override
    public Type[] getPropertyTypes() {
        return new Type[] {BIG_DECIMAL, BIG_DECIMAL};
    }

    @Override
    public Object getPropertyValue(final Object component, final int property) throws HibernateException {
        if (component == null) {
            return null;
        }

        final Ratio ratio = (Ratio) component;
        switch (property) {
            case 0:
                return ratio.breachEncapsulationOf_numerator();
            case 1:
                return ratio.breachEncapsulationOf_denominator();
            default:
                throw new HibernateException("Property index " + property + " is out of bounds. " +
                        "Properties are: " + Arrays.toString(getPropertyNames()));
        }
    }

    @Override
    public Class returnedClass() {
        return Ratio.class;
    }

    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
        final BigDecimal numerator = (BigDecimal) BIG_DECIMAL.nullSafeGet(rs, names[0]);
        final BigDecimal denominator = (BigDecimal) BIG_DECIMAL.nullSafeGet(rs, names[1]);

        if (numerator == null || denominator == null) {
            return null;
        }

        return Ratio.of(numerator.stripTrailingZeros(), denominator.stripTrailingZeros());
    }

    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
        final Ratio ratio = (Ratio) value;

        final BigDecimal numerator = (ratio == null) ? null : ratio.breachEncapsulationOf_numerator();
        final BigDecimal denominator = (ratio == null) ? null : ratio.breachEncapsulationOf_denominator();

        BIG_DECIMAL.nullSafeSet(st, numerator, index);
        BIG_DECIMAL.nullSafeSet(st, denominator, index + 1);
    }
}
